package com.yeyks.controller.hotel;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yeyks.account.dal.dao.AccountInfoMapper;
import com.yeyks.account.dal.domain.AccountInfo;
import com.yeyks.account.utils.AccountUtil;
import com.yeyks.annotation.Login;
import com.yeyks.annotation.LoginUser;
import com.yeyks.annotation.NeedToken;
import com.yeyks.annotation.SystemLog;
import com.yeyks.common.ajax.AjaxResponseBody;
import com.yeyks.common.base.Arguments;
import com.yeyks.common.constants.AccountType;
import com.yeyks.common.constants.SysLogMsg;
import com.yeyks.common.dto.mq.EsUpdateMessage;
import com.yeyks.common.em.HotelStatus;
import com.yeyks.common.em.ResponseStatus;
import com.yeyks.common.exception.PermissionInvalidException;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.common.exception.TokenInvalidException;
import com.yeyks.common.result.OrderPickWebSocket;
import com.yeyks.common.utils.DateUtils;
import com.yeyks.common.utils.Result;
import com.yeyks.common.utils.Splitters;
import com.yeyks.common.utils.TextValidator;
import com.yeyks.common.utils.webutil.Utility;
import com.yeyks.commonReference.append.rocketmq.service.producer.MQProducerService;
import com.yeyks.commonReference.service.account.AccountInfoService;
import com.yeyks.commonReference.service.hotel.HotelInfoService;
import com.yeyks.commonReference.service.message.MessageService;
import com.yeyks.commonReference.service.order.OrderPickRecordService;
import com.yeyks.hotel.dal.dao.CompanyInfoMapper;
import com.yeyks.hotel.dal.dao.HotelInfoMapper;
import com.yeyks.hotel.dal.dao.RoomInfoMapper;
import com.yeyks.hotel.dal.domain.CompanyInfo;
import com.yeyks.hotel.dal.domain.HotelInfo;
import com.yeyks.hotel.dal.domain.RoomInfo;
import com.yeyks.hotel.dto.HotelCreateParam;
import com.yeyks.hotel.dto.PayAccountDTO;
import com.yeyks.hotel.param.HotelQueryParam;
import com.yeyks.web.AccountUtils;
import com.yeyks.websocket.SendMessageBean;
import com.yeyks.websocket.WebSocket;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import jodd.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.util.*;

/**
 * 酒店相关功能接口
 *
 * @author Beacon
 * @version $Id: HotelController.java, v 0.1 2018年07月31日 14:50 Beacon Exp $
 */
@Api(tags = "酒店模块")
@RestController
@RequestMapping(value = "/ajax/hotel")
public class HotelController {
    private Logger logger = LoggerFactory.getLogger(HotelController.class);

    @Autowired
    HotelInfoMapper hotelInfoMapper;
    @Autowired
    AccountInfoMapper accountInfoMapper;
    @Autowired
    CompanyInfoMapper companyInfoMapper;
    @Autowired
    RoomInfoMapper roomInfoMapper;
    @Autowired
    AccountInfoService accountService;
    @Autowired
    MessageService messageService;
    @Autowired
    HotelInfoService hotelService;
    @Autowired
    private OrderPickRecordService orderPickRecordService;
    @Autowired
    private WebSocket webSocket;
    @Autowired
    private MQProducerService mQProducerService;


    @RequestMapping(value = "/mgrsetinfo", method = RequestMethod.POST)
    @Login
    @SystemLog(value = SysLogMsg.HOTEL_UPDATE_MSG)
    public ResponseEntity<?> mgrsetinfo(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "force", defaultValue = "false", required = true) Boolean force,
            @RequestParam(name = "draft", defaultValue = "false", required = true) Boolean draft,
            @RequestParam(name = "provinceCode", defaultValue = "", required = false) String provinceCode,
            @RequestParam(name = "cityCode", defaultValue = "", required = false) String cityCode,
            @RequestParam(name = "countryCode", defaultValue = "", required = false) String countryCode,
            @ApiIgnore @LoginUser AccountInfo accountInfo,
            HotelInfo hotelInfo
    ) {
        AjaxResponseBody response = new AjaxResponseBody();

        try {
//            List<HotelInfo> hotelInfoList = null;
            HotelInfo existHotelInfo = null;
            if (accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            } else if (accountInfo.getType() == AccountType.CityManager) {
                hotelInfo.setAdminId(AccountUtil.getOperationUserId(accountInfo));
//                hotelInfoList = hotelService.searchHotelsByAdministrator(hotelInfo.getAdminId());
//
//                if (hotelInfo.getId() == null || hotelInfo.getId() == 0) {
//
//                } else {
//                    for (HotelInfo hi : hotelInfoList) {
//                        if (hi.getId().longValue() == hotelInfo.getId().longValue()) {
//                            existHotelInfo = hi;
//                        }
//                    }
//
//                    if (existHotelInfo == null) {
//                        throw new Exception("cannot find Hotel Information");
//                    }
//                }
                hotelInfo.setStatus(draft ? HotelStatus.PreCheck : HotelStatus.PreSubmit);
                existHotelInfo = hotelService.selectHotelInfoById(hotelInfo.getId());
            } else if (accountInfo.getType() == AccountType.HotelManager) {
                hotelInfo.setOperatorId(AccountUtil.getOperationUserId(accountInfo));
//                hotelInfoList = hotelService.searchHotelsByOperator(hotelInfo.getOperatorId());
//                if (hotelInfoList != null && !hotelInfoList.isEmpty()) {
//                    existHotelInfo = hotelInfoList.get(0);
//                }
                existHotelInfo = hotelService.searchHotelByOperator(hotelInfo.getOperatorId());
                // 酒店管理员不允许修改酒店提成比例
                hotelInfo.setParentTax(null);

                // 不允许 修改状态
                hotelInfo.setStatus(null);
            } else {
                // 省代与平台管理员直接审核成功
                hotelInfo.setGmtModified(new Date());
                if (accountInfo.getType() == AccountType.Administrator) {
                    hotelInfo.setStatus(HotelStatus.Pass);
                }
                int rec = 0;
                if (!force) {
                    rec = hotelInfoMapper.updateIfNotNullByPrimaryKey(hotelInfo);
                } else {
                    rec = hotelInfoMapper.updateByPrimaryKey(hotelInfo);
                }
                if (rec == 0) {
                    throw new Exception("Updated 0 row.");
                }
//                response.setBody(rec);
//                response.setCode(ResponseStatus.RS_SUCCESS.getCode());
//                response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
//                return ResponseEntity.ok(response);
            }

//            if (existHotelInfo == null) {
//                hotelInfo.setGmtCreate(new Date());
//                hotelInfo.setGmtModified(new Date());
//
//                if (hotelInfo.getValid() == null) {
//                    hotelInfo.setValid(true);
//                }
//
//                hotelInfoMapper.insertReturnId(hotelInfo);
//            } else {
//                HotelInfo origHotelInfo = existHotelInfo;
//
//                hotelInfo.setId(origHotelInfo.getId());
//                hotelInfo.setGmtModified(new Date());
//
//                if (!force) {
//                    hotelInfoMapper.updateIfNotNullByPrimaryKey(hotelInfo);
//                } else {
//                    hotelInfoMapper.updateByPrimaryKey(hotelInfo);
//                }
//            }
//            //修改酒店固话信息到account_info表中tel字段中，过渡期间使用，后面这个可以去掉
//            AccountInfo info = accountInfoMapper.selectByPrimaryKey(hotelInfo.getOperatorId());
//            if (info != null) {
//                info.setTel(hotelInfo.getTel());
//                info.setPhone(hotelInfo.getPhone());
//                accountInfoMapper.updateById(info);
//            }
//            HotelInfo origHotelInfo = existHotelInfo;
//
//            hotelInfo.setId(origHotelInfo.getId());
            hotelInfo.setGmtModified(new Date());

            if (!force) {
                hotelInfoMapper.updateIfNotNullByPrimaryKey(hotelInfo);
            } else {
                hotelInfoMapper.updateByPrimaryKey(hotelInfo);
            }
            //修改酒店管理员表中省市区编码
            UpdateWrapper<AccountInfo> updateWrapper = new UpdateWrapper<AccountInfo>();
            boolean flag = false;
            if(StringUtil.isNotBlank(provinceCode)){
                updateWrapper.set(AccountInfo.PROVINCE_CODE,provinceCode);
                flag = true;
            }
            if(StringUtil.isNotBlank(cityCode)){
                updateWrapper.set(AccountInfo.CITY_CODE,cityCode);
                flag = true;
            }
            if(StringUtil.isNotBlank(countryCode)){
                updateWrapper.set(AccountInfo.COUNTRY_CODE,countryCode);
                flag = true;
            }
            updateWrapper.eq(AccountInfo.ID,hotelInfo.getOperatorId());
            if(flag) {
                accountService.update(updateWrapper); //修改省市区编码
            }



            response.setBody(hotelInfo);
            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }
        //发送mq
        sendMqMessage(hotelInfo.getId());
        return ResponseEntity.ok(response);
    }

    @RequestMapping(value = "/listHotelUnderAccount", method = RequestMethod.POST)
    public ResponseEntity<?> listHotelUnderAccount(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "accountId", defaultValue = "", required = true) Integer accountId,
            @RequestParam(name = "count", defaultValue = "", required = true) Integer count,
            @RequestParam(name = "pageNum", defaultValue = "", required = true) Integer pageNum,
            @RequestParam(name = "pageSize", defaultValue = "", required = true) Integer pageSize
    ) {
        AjaxResponseBody<Map> response = AjaxResponseBody.getMapAjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() >= AccountType.HotelManager) {
                throw new PermissionInvalidException();
            }
            Integer offset = (pageNum != null && pageSize != null) ? (pageNum - 1) * pageSize : null;
            AccountInfo info = accountInfoMapper.selectByPrimaryKey(accountId);

            List<HotelInfo> hotelInfos = null;

            if (info.getType().equals(AccountType.ProvinceManager)) //省代签约酒店列表
            {
                hotelInfos = hotelInfoMapper.queryListByProvinceId(accountId, offset, pageSize);
            } else if (info.getType().equals(AccountType.CityAgent)) //市代
            {
                hotelInfos = hotelInfoMapper.queryListByCityAgentId(accountId, offset, pageSize);
            } else if (info.getType().equals(AccountType.CityManager)) //区县运营中心
            {
                hotelInfos = hotelInfoMapper.queryListByAdminId(accountId, offset, pageSize);
            }
            response.getBody().put("hotels", hotelInfos);
            response.getBody().put("count", count);
            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(ResponseStatus.RS_FAIL.getMsg());
        }

        return ResponseEntity.ok(response);
    }

    /**
     * 根据一定的条件查询酒店信息
     *
     * @return
     */
    @ApiOperation(value = "查询酒店列表", notes = "查询酒店列表")
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    public ResponseEntity<?> list(HotelQueryParam hotelQueryParam) {
        AjaxResponseBody<Map> response = AjaxResponseBody.getMapAjaxResponseBody();

        AccountInfo accountInfo = accountService.token2AccountInfo(hotelQueryParam.getToken());
        if (AccountType.HotelManager == accountInfo.getType() || AccountType.VipCardMerchant == accountInfo.getType()) {
            throw new ServiceException("无权限操作");
        }
        List<Integer> statusList = Utility.str2intList(hotelQueryParam.getStatus());
        List<Integer> vipFlagList = Utility.str2intList(hotelQueryParam.getVipFlag());
        List<Integer> adminIds = null;
        if (accountInfo.getType() == AccountType.CityManager) {
            adminIds = new ArrayList<>();
            adminIds.add(AccountUtil.getOperationUserId(accountInfo));
        } else if (accountInfo.getType() == AccountType.ProvinceManager) {
            adminIds = new ArrayList<>();

            List<AccountInfo> accountInfos = new ArrayList<>();//accountInfoMapper.selectTwoChildren(accountInfo.getId());
            if (null != accountInfo.getManagerId()) {
                accountInfos = accountInfoMapper.selectTwoChildren(accountInfo.getManagerId());
            } else {
                accountInfos = accountInfoMapper.selectTwoChildren(accountInfo.getId());
            }
            for (AccountInfo ai : accountInfos) {
                adminIds.add(AccountUtil.getOperationUserId(ai));
            }
        } else if (accountInfo.getType() == AccountType.CityAgent) {
            adminIds = new ArrayList<>();
            List<Integer> ids = new ArrayList<>();
            ids.add(AccountUtil.getOperationUserId(accountInfo));
            List<AccountInfo> accountInfos = accountInfoMapper.selectChildren(ids);
            for (AccountInfo ai : accountInfos) {
                adminIds.add(AccountUtil.getOperationUserId(ai));
            }
        } else if (accountInfo.getType() == AccountType.OperateMerchant || accountInfo.getType() == AccountType.ServiceMerchant) {

            hotelQueryParam.setDeveloperId(accountInfo.getId());
        }

        hotelQueryParam.setAdminIds(adminIds);
        hotelQueryParam.setStatusList(statusList);
        hotelQueryParam.setVipFlagList(vipFlagList);
        if (null != hotelQueryParam.getGmtModifiedStart()) {
            hotelQueryParam.setGmtCreateStart(new Date(hotelQueryParam.getGmtModifiedStart()));
        }
        if (null != hotelQueryParam.getGmtModifiedEnd()) {
            hotelQueryParam.setGmtCreateEnd(new Date(hotelQueryParam.getGmtModifiedEnd()));
        }
        if ((hotelQueryParam.getPageNum() != null && hotelQueryParam.getPageSize() != null)) {
            hotelQueryParam.setOffset((hotelQueryParam.getPageNum() - 1) * hotelQueryParam.getPageSize());
        }
        hotelQueryParam.setUserType(accountInfo.getType());

        List<Map> hotelInfos = hotelService.queryHotelList(hotelQueryParam);

        int count = hotelService.queryHotelListCount(hotelQueryParam);
        response.getBody().put("hotels", hotelInfos);
        response.getBody().put("count", count);
        response.setCode(ResponseStatus.RS_SUCCESS.getCode());
        response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());

        return ResponseEntity.ok(response);
    }

    /**
     * @param hotelQueryParam
     * @return
     */
    @ApiOperation(value = "运营商查询酒店列表", notes = "运营商/服务商查询酒店列表")
    @RequestMapping(value = "/listByDeveloper", method = RequestMethod.POST)
    @Login
    public ResponseEntity<?> listByDeveloper(HotelQueryParam hotelQueryParam) {
        AjaxResponseBody<Map> response = AjaxResponseBody.getMapAjaxResponseBody();

        AccountInfo accountInfo = accountService.token2AccountInfo(hotelQueryParam.getToken());
        List<Integer> statusList = Utility.str2intList(hotelQueryParam.getStatus());
        hotelQueryParam.setDeveloperId(accountInfo.getId());
        hotelQueryParam.setStatusList(statusList);

        if (null != hotelQueryParam.getGmtModifiedStart()) {
            hotelQueryParam.setGmtCreateStart(new Date(hotelQueryParam.getGmtModifiedStart()));
        }
        if (null != hotelQueryParam.getGmtModifiedEnd()) {
            hotelQueryParam.setGmtCreateEnd(new Date(hotelQueryParam.getGmtModifiedEnd()));
        }
        if ((hotelQueryParam.getPageNum() != null && hotelQueryParam.getPageSize() != null)) {
            hotelQueryParam.setOffset((hotelQueryParam.getPageNum() - 1) * hotelQueryParam.getPageSize());
        }
        hotelQueryParam.setUserType(accountInfo.getType());
        hotelQueryParam.setLoginUserId(accountInfo.getId());

        List<Map> hotelInfos = hotelService.queryHotelListByDeveloper(hotelQueryParam);
        int count = hotelService.queryHotelListCountByDeveloper(hotelQueryParam);
        response.getBody().put("hotels", hotelInfos);
        response.getBody().put("count", count);
        response.setCode(ResponseStatus.RS_SUCCESS.getCode());
        response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());

        return ResponseEntity.ok(response);
    }


    private void getMoreInfo(HotelInfo hotelInfo, AjaxResponseBody<Map> responseBody) {
        try {
            CompanyInfo companyInfo = companyInfoMapper.selectByPrimaryKey(hotelInfo.getCompanyId());
            responseBody.getBody().put("company_info", companyInfo);
        } catch (Throwable e) {
            e.printStackTrace();
            logger.warn("获取酒店对应公司信息失败", e);
        }
        try {
            List<RoomInfo> roomInfos = roomInfoMapper.selectByHotelId(hotelInfo.getId());
            responseBody.getBody().put("room_infos", roomInfos);
        } catch (Throwable e) {
            e.printStackTrace();
            logger.warn("获取酒店对应房间列表信息失败", e);
        }

        try {
            AccountInfo cityMgrAccountInfo = accountService.findByPrimaryKey(hotelInfo.getAdminId());
            responseBody.getBody().put("city_mgr", cityMgrAccountInfo);

            try {
                AccountInfo branchAccountInfo = accountService.findByPrimaryKey(cityMgrAccountInfo.getParentId());
                responseBody.getBody().put("branch_mgr", branchAccountInfo);
            } catch (Throwable e) {
                e.printStackTrace();
                logger.warn("获取酒店对应分管账户信息失败", e);
            }

        } catch (Throwable e) {
            e.printStackTrace();
            logger.warn("获取酒店对应城市运营商信息失败", e);
        }

        try {
            AccountInfo hotelAccountInfo = accountInfoMapper.selectByPrimaryKey(hotelInfo.getOperatorId());
            responseBody.getBody().put("hotel_mgr", hotelAccountInfo);
        } catch (Throwable e) {
            e.printStackTrace();
            logger.warn("获取酒店对应账户信息失败", e);
        }
    }

    /**
     * 通过酒店id查询酒店的相关信息
     *
     * @param token
     * @param id
     * @param all
     * @return
     */
    @Login
    @RequestMapping(value = "/mgrgetinfo", method = RequestMethod.POST)
    public ResponseEntity<?> mgrgetinfo(
            @ApiIgnore @LoginUser AccountInfo loginUser,
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "id", defaultValue = "", required = false) Integer id,
            @RequestParam(name = "all", defaultValue = "", required = false) Boolean all
    ) {
        AjaxResponseBody<Map> responseBody = AjaxResponseBody.getMapAjaxResponseBody();

        boolean isHotelMgr = false;
//            AccountInfo loginUser = accountService.token2AccountInfo(token);
        isHotelMgr = (loginUser.getType() == AccountType.HotelManager);

        if (isHotelMgr && (id == null || id == 0)) {
            // 酒店管理员获得自己的酒店信息
            HotelInfo hotelInfo = hotelService.searchHotelByOperator(AccountUtil.getOperationUserId(loginUser));
            if (null == hotelInfo) {
                responseBody.setCode(ResponseStatus.RS_HOTEL_NOT_EXIST.getCode());
                responseBody.setMsg(ResponseStatus.RS_HOTEL_NOT_EXIST.getMsg());
            } else {
                responseBody.getBody().put("hotel_info", hotelInfo);
                if (all != null && all) {
                    getMoreInfo(hotelInfo, responseBody);
                }
                responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
                responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
            }
        } else if (id != null && id != 0) {
            // 其它管理员可以获得任意酒店信息
            HotelInfo hotelInfo = hotelInfoMapper.selectByPrimaryKey(id);
            if (hotelInfo == null) {
                responseBody.setCode(ResponseStatus.RS_HOTEL_NOT_EXIST.getCode());
                responseBody.setMsg(ResponseStatus.RS_HOTEL_NOT_EXIST.getMsg());
            } else {
                responseBody.getBody().put("hotel_info", hotelInfo);

                if (all != null && all) {
                    getMoreInfo(hotelInfo, responseBody);
                }
                responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
                responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
            }
        } else {
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 酒店房间审核是否通过
     *
     * @param hotelId
     * @param pass
     * @param comment
     * @return
     */
    @NeedToken
    @SystemLog(value = SysLogMsg.HOTEL_UPDATE_ROOM_PASS)
    @RequestMapping(value = "/adminAudit", method = RequestMethod.POST)
    public ResponseEntity<?> adminAudit(
            @RequestParam(name = "hotelId", defaultValue = "", required = true) Integer hotelId,
            @RequestParam(name = "pass", defaultValue = "true", required = true) Boolean pass,
            @RequestParam(name = "comment", defaultValue = "", required = true) String comment

    ) {
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = AccountUtils.getLoginUser();
            if (accountInfo.getType() != AccountType.Administrator &&
                    accountInfo.getType() != AccountType.ProvinceManager &&
                    accountInfo.getType() != AccountType.CityAgent) {
                throw new PermissionInvalidException();
            }

            HotelInfo hotelInfo = hotelInfoMapper.selectByPrimaryKey(hotelId);
            if (hotelInfo == null) {
                throw new Exception("cannot find hotel information.");
            } else if (hotelInfo.getStatus() != HotelStatus.PreCheck) {
                throw new Exception("hotel status is not precheck.");
            }

            if (!pass) {
                hotelInfo.setExtraInfo(Utility.setExtraInfo(hotelInfo.getExtraInfo(), "nopass_comment", comment));
            }

            List<Integer> ids = new ArrayList<>();
            ids.add(hotelId);
            int res = hotelInfoMapper.updateStatusByIds(ids,
                    pass ? HotelStatus.Pass : HotelStatus.NoPass,
                    hotelInfo.getExtraInfo());

            if (res == 0) {
                throw new Exception("update 0 rows");
            } else if (pass) {
                messageService.passHotelInfo(hotelInfo);
                //websocket推送一条消息
                //通过酒店id获取酒店上级用户名
                List<Integer> userIds = accountService.getParentId(accountInfo.getId());
                if (null != userIds) {
                    userIds.forEach(e -> webSocket.sendMessageToUser(e, SendMessageBean.getInformMsg()));
                }
            } else if (!pass) {
                messageService.nopassHotelInfo(hotelInfo);
            }

            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }
        sendMqMessage(hotelId);
        return ResponseEntity.ok(response);
    }

    /**
     * 酒店是否启用
     *
     * @param hotelId
     * @param valid
     * @return
     */
    @SystemLog(value = SysLogMsg.HOTEL_UPDATE_USE)
    @Login
    @ApiOperation(value = "酒店停用启用")
    @RequestMapping(value = "/adminValid", method = RequestMethod.POST)
    public Result adminValid(
            @ApiIgnore @LoginUser AccountInfo loginUser,
            @RequestParam(name = "hotelId", defaultValue = "", required = true) Integer hotelId,
            @RequestParam(name = "valid", defaultValue = "true", required = true) Boolean valid
    ) {

        if (loginUser.getType() != AccountType.Administrator &&
                loginUser.getType() != AccountType.ProvinceManager &&
                loginUser.getType() != AccountType.CityAgent) {
            throw new ServiceException("无操作权限");
        }
        int res = hotelService.updateValidByIds(hotelId, valid);
        if (res == 0) {
            return Result.error("禁用酒店操作失败");
        }
        //发送mq
        sendMqMessage(hotelId);
        return Result.ok();
    }

    @ApiOperation(value = "总公司设置付款账户", notes = "总公司修改酒店付款账户")
    @RequestMapping(value = "/updatePayAccount", method = RequestMethod.POST)
    public ResponseEntity<?> updatePayAccountByAdmin(@RequestBody PayAccountDTO payAccountDTO) {
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(payAccountDTO.getToken());
            if (!accountInfo.getType().equals(AccountType.Administrator)) {
                throw new PermissionInvalidException();
            }

//            String oldPayAccountsJson = Utility.getExtraInfo(accountInfo.getExtraInfo(), "pay_accounts");
//            JSONObject jsonObject = new JSONObject();
//            if(Arguments.notEmpty(oldPayAccountsJson))
//            {
//                jsonObject = Utility.toJsonObject(oldPayAccountsJson) ;
//            }

            Map<String, String> payAccounts = new HashMap<>();
            payAccounts.put("bankName", payAccountDTO.getBankName());
            payAccounts.put("branchBankName", payAccountDTO.getBranchBankName());
            payAccounts.put("userName", payAccountDTO.getUserName());
            payAccounts.put("bankCard", payAccountDTO.getBankCard());
            String extraInfo = Utility.setExtraInfo(accountInfo.getExtraInfo(), "pay_accounts", payAccounts);
            //更新帐户表中的账户信息
            int rec = accountInfoMapper.updateExtraInfoById(accountInfo.getId(), extraInfo);
            //更新酒店表中的账户信息，过度期间将酒店账号信息在酒店表中也保存一份
            hotelInfoMapper.updatePayAccountById(payAccountDTO.getHotelId(), extraInfo);
            if (rec > 0) {
                response.setCode(ResponseStatus.RS_SUCCESS.getCode());
                response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
            } else {
                response.setCode(ResponseStatus.RS_FAIL.getCode());
                response.setMsg(ResponseStatus.RS_FAIL.getMsg());
            }
        } catch (Exception e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }
        //发送mq
        sendMqMessage(payAccountDTO.getHotelId());
        return ResponseEntity.ok(response);
    }

    @ApiOperation(value = "设置付款账户", notes = "设置付款账户信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "token"),
            @ApiImplicitParam(name = "bankName", value = "银行名称", required = true),
            @ApiImplicitParam(name = "branchBankName", value = "支行名称", required = true),
            @ApiImplicitParam(name = "userName", value = "用户名", required = true),
            @ApiImplicitParam(name = "bankCard", value = "银行卡号", required = true)
    })
    @RequestMapping(value = "/setPayAccounts", method = RequestMethod.POST)
    public ResponseEntity<?> setPayAccounts(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "bankName", defaultValue = "", required = true) String bankName,
            @RequestParam(name = "branchBankName", defaultValue = "", required = true) String branchBankName,
            @RequestParam(name = "userName", defaultValue = "", required = true) String userName,
            @RequestParam(name = "bankCard", defaultValue = "", required = false) String bankCard
    ) {
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            }
            Map<String, String> payAccounts = new HashMap<>();
            payAccounts.put("bankName", bankName);
            payAccounts.put("branchBankName", branchBankName);
            payAccounts.put("userName", userName);
            payAccounts.put("bankCard", bankCard);
            String extraInfo = Utility.setExtraInfo(accountInfo.getExtraInfo(), "pay_accounts", payAccounts);
            //保存到酒店表里
            HotelInfo hotel = hotelService.selectHotelInfoByOperatorId(accountInfo.getId());
            if (hotel != null) {
                hotelInfoMapper.updatePayAccountById(hotel.getId(), extraInfo);
            }
            sendMqMessage(hotel.getId());
            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(response);
    }

    @ApiOperation(value = "设置酒店免佣期", notes = "设置酒店免佣期")
    @RequestMapping(value = "/setNoFeeDate", method = RequestMethod.POST)
    @Login
    @SystemLog(value = SysLogMsg.HOTEL_UPDATE_NO_TAX)
    public ResponseEntity<?> setNoFeeDate(
            @ApiIgnore @LoginUser AccountInfo loginUser,
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "hotelId", defaultValue = "", required = true) Integer hotelId,
            @RequestParam(name = "startDateNoTax", defaultValue = "", required = true) String startDateNoTax,
            @RequestParam(name = "endDateNoTax", defaultValue = "", required = true) String endDateNoTax
    ) {
        AjaxResponseBody response = new AjaxResponseBody();
        try {
            if (!loginUser.getType().equals(AccountType.Administrator)) {
                throw new PermissionInvalidException();
            }
            //设置酒店免佣期
            hotelService.updateNoFeeDate(hotelId, DateUtils.yyyyMMddToDate(startDateNoTax), DateUtils.yyyyMMddToDate(endDateNoTax));
            sendMqMessage(hotelId);
        } catch (Exception e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(ResponseStatus.RS_FAIL.getMsg());
        }
        return ResponseEntity.ok(response);
    }

    @ApiOperation(value = "查询酒店免佣期到期列表", notes = "查询酒店免佣期到期列表")
    @RequestMapping(value = "/checkNoTaxHotel", method = RequestMethod.POST)
    public AjaxResponseBody<List<HotelInfo>> checkNoTaxHotel() {

        List<HotelInfo> hotelInfos = hotelService.searchHotelsNoTaxExpired(null);

        return AjaxResponseBody.success(hotelInfos);
    }


    @ApiOperation(value = "酒店获取付款账户", notes = "根据token获取账户")
    @ApiImplicitParam(name = "token", value = "token,notblank")
    @RequestMapping(value = "/getPayAccounts", method = RequestMethod.POST)
    public ResponseEntity<?> getPayAccounts(
            @RequestParam(name = "token", defaultValue = "", required = true) String token
    ) {
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            }
            HotelInfo hotel = hotelService.selectHotelInfoByOperatorId(accountInfo.getId());
            if (hotel != null) {
                response.setBody(Utility.getExtraInfo(hotel.getPayAccounts(), "pay_accounts"));
                response.setCode(ResponseStatus.RS_SUCCESS.getCode());
                response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
            }
        }catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(response);
    }

    /**
     * 查询指定条件下代理商的酒店数量
     *
     * @param token
     * @param dtStart
     * @param dtEnd
     * @return
     */
    @RequestMapping(value = "/getNewCount", method = RequestMethod.POST)
    public ResponseEntity<?> getNewCount(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "dtStart", defaultValue = "0", required = true) Long dtStart,
            @RequestParam(name = "dtEnd", defaultValue = "0", required = true) Long dtEnd
    ) {
        AccountInfo accountInfo = accountService.token2AccountInfo(token);
        if (accountInfo.getType().equals(AccountType.User)
                || accountInfo.getType().equals(AccountType.HotelManager)) {
            throw new ServiceException("用户权限不够");
        }
        Integer userId;
        if (null != accountInfo.getManagerId()) {
            userId = accountInfo.getManagerId();
        } else {
            userId = accountInfo.getId();
        }
        int count = hotelService.getNewHotelCount(new Date(dtStart), new Date(dtEnd), userId, accountInfo.getType());
        return ResponseEntity.ok(AjaxResponseBody.success(count));
    }

    /**
     * 修改酒店的extro信息
     *
     * @param token
     * @param checkinTime
     * @param checkoutTime
     * @param extraNote
     * @return
     */
    @SystemLog(value = SysLogMsg.HOTEL_UPDATE_EXTRA)
    @RequestMapping(value = "/mgrSetCheckRule", method = RequestMethod.POST)
    public ResponseEntity<?> mgrSetCheckRule(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "checkinTime", defaultValue = "", required = true) String checkinTime,
            @RequestParam(name = "checkoutTime", defaultValue = "", required = true) String checkoutTime,
            @RequestParam(name = "extraNote", defaultValue = "", required = true) String extraNote
    ) {
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() != AccountType.HotelManager) {
                throw new PermissionInvalidException();
            }

            List<HotelInfo> hotelInfos = hotelService.searchHotelsByOperator(AccountUtil.getOperationUserId(accountInfo));
            if (hotelInfos == null || hotelInfos.size() == 0) {
                throw new Exception("no hotel information");
            }

            HotelInfo hotelInfo = hotelInfos.get(0);

            JSONObject extraObject = Utility.toJsonObject(hotelInfo.getExtraInfo());
            if (extraObject == null) {
                throw new Exception("get hotel extra information failed");
            }

            extraObject.put("checkinTime", checkinTime);
            extraObject.put("checkoutTime", checkoutTime);
            extraObject.put("extraNote", extraNote);

            HotelInfo updateHotelInfo = new HotelInfo();
            updateHotelInfo.setId(hotelInfo.getId());
            updateHotelInfo.setExtraInfo(extraObject.toJSONString());

            hotelInfo.setExtraInfo(extraObject.toJSONString());
            int rec = hotelInfoMapper.updateIfNotNullByPrimaryKey(updateHotelInfo);
            if (rec == 0) {
                throw new Exception("updated 0 row.");
            }

            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
            sendMqMessage(hotelInfo.getId());
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(response);
    }

    /**
     * 新增酒店(同时需要先增加公司信息，再增加用户，后增加酒店)
     *
     * @param loginUser
     * @param createParam
     * @return
     */
    @ApiOperation(value = "添加酒店", notes = "添加酒店")
    @SystemLog(value = SysLogMsg.HOTEL_ADD)
    @Login
    @RequestMapping(value = "/addV2", method = RequestMethod.POST)
    public AjaxResponseBody<Integer> addV2(@ApiIgnore @LoginUser AccountInfo loginUser, HotelCreateParam createParam) {
        checkParam(createParam.getPhone(), createParam.getPassword(), createParam.getUsername());
        if (loginUser.getType() == null || (loginUser.getType() != null && !loginUser.getType().equals(AccountType.CityManager))) {
            throw new ServiceException("当前操作人非法");
        }
        Integer hotelId = hotelService.createHotel(createParam, loginUser);
        sendMqMessage(hotelId);
        return AjaxResponseBody.success(hotelId);
    }

    @ApiOperation(value = "总公司添加酒店", notes = "总公司添加酒店")
    @SystemLog(value = "总公司新增酒店")
    @Login
    @RequestMapping(value = "/addHotelByAdmin", method = RequestMethod.POST)
    public AjaxResponseBody<Integer> addHotelByAdmin(@ApiIgnore @LoginUser AccountInfo loginUser, HotelCreateParam createParam) {
        checkParam(createParam.getPhone(), createParam.getPassword(), createParam.getUsername());
        if (null == loginUser.getType() || (!loginUser.getType().equals(AccountType.Administrator))) {
            throw new ServiceException("当前操作人非法");
        }
        Integer hotelId = hotelService.createHotel(createParam, loginUser);
        sendMqMessage(hotelId);
        return AjaxResponseBody.success(hotelId);
    }


    private void checkParam(String phone, String password, String username) {

        Arguments.strIsNull(phone, "商家手机号输入为空");
        Arguments.isTrue(!TextValidator.MOBILE.boolCheck(phone), "商家手机号输入为空");
        Arguments.strIsNull(username, "用户名不能为空");
        Arguments.strIsNull(password, "密码不能为空");
//        if (password.length() < 6 || password.length() > 16) {
//            throw new ServiceException("密码的有效长度为6-16位");
//        }
    }

    @ApiOperation(value = "升级甄选/优选酒店", notes = "升级甄选/优选酒店")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "hotelId", value = "酒店id", dataType = "Integer"),
            @ApiImplicitParam(paramType = "query", name = "developerId", value = "开发商/服务商ID", dataType = "Integer"),
            @ApiImplicitParam(paramType = "query", name = "vipFlag", value = "是否甄选,0否1是", dataType = "Integer")
    })
    @SystemLog(value = SysLogMsg.HOTEL_UPTO_VIP)
    @RequestMapping(value = "/upgradeVipHotel", method = RequestMethod.POST)
    public AjaxResponseBody upgradeVipHotel(Integer hotelId, Integer developerId,Integer vipFlag) {
        return hotelService.upgradeVipHotel(hotelId, developerId,vipFlag);
    }

    @ApiOperation(value = "升级成优享酒店", notes = "升级成优享酒店")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "hotelId", value = "酒店id", dataType = "Integer"),
            @ApiImplicitParam(paramType = "query", name = "developerId", value = "开发商ID", dataType = "Integer")
    })
    @SystemLog(value = SysLogMsg.HOTEL_UPTO_JIP)
    @RequestMapping(value = "/upgradeJipHotel", method = RequestMethod.POST)
    public AjaxResponseBody upgradeJipHotel(Integer hotelId, Integer developerId) {
        return hotelService.upgradeJipHotel(hotelId, developerId);
    }

    @SystemLog(value = SysLogMsg.HOTEL_UPDATE_REMARK)
    @ApiOperation(value = "修改酒店备注", notes = "修改酒店备注")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "hotelId", value = "酒店id", dataType = "Integer"),
            @ApiImplicitParam(paramType = "query", name = "remark", value = " ", dataType = "String")
    })
    @RequestMapping(value = "/modifyRemark", method = RequestMethod.POST)
    public AjaxResponseBody modifyRemark(Integer hotelId, String remark) {
        AjaxResponseBody res = hotelService.modifyRemark(hotelId, remark);
        sendMqMessage(hotelId);
        return res;
    }

    @SystemLog(value = SysLogMsg.HOTEL_PAREN_TAX)
    @ApiOperation(value = "修改酒店抽成比例", notes = "修改酒店抽成比例")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "hotelId", value = "酒店id", dataType = "Integer"),
            @ApiImplicitParam(paramType = "query", name = "parentTax", value = "", dataType = "Integer")
    })
    @RequestMapping(value = "/modifyParentTax", method = RequestMethod.POST)
    public AjaxResponseBody modifyParentTax(Integer hotelId, Integer parentTax) {
        AjaxResponseBody res = hotelService.modifyParentTax(hotelId,parentTax);
        sendMqMessage(hotelId);
        return res;
    }

    @SystemLog(value = SysLogMsg.HOTEL_SUBMIT)
    @ApiOperation(value = "提交酒店", notes = "提交酒店")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "hotelId", value = "酒店id", dataType = "Integer")
    })
    @RequestMapping(value = "/submitHotel", method = RequestMethod.POST)
    public AjaxResponseBody submitHotel(Integer hotelId) {
        AjaxResponseBody res = hotelService.submitHotel(hotelId);
        return res;
    }

    @SystemLog(value = SysLogMsg.HOTEL_UPDATE_DEVELOPER)
    @ApiOperation(value = "设置酒店开发商", notes = "设置酒店开发商")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "hotelId", value = "酒店id", dataType = "Integer", required = true),
            @ApiImplicitParam(paramType = "query", name = "developerId", value = " ", dataType = "Integer", required = true)
    })
    @RequestMapping(value = "/setHotelDeveloper", method = RequestMethod.POST)
    public AjaxResponseBody setHotelDeveloper(Integer hotelId, Integer developerId) {
        AjaxResponseBody res = hotelService.setHotelDeveloper(hotelId, developerId);
        sendMqMessage(hotelId);
        return res;
    }

    @SystemLog(value = SysLogMsg.HOTEL_UPDATE_AGNET)
    @ApiOperation(value = "设置酒店代理商", notes = "设置酒店代理商")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "hotelId", value = "酒店id", dataType = "Integer", required = true),
            @ApiImplicitParam(paramType = "query", name = "agentId", value = " ", dataType = "Integer", required = true)
    })
    @RequestMapping(value = "/setHotelAgent", method = RequestMethod.POST)
    public AjaxResponseBody setHotelAgent(Integer hotelId, Integer agentId) {

        AjaxResponseBody res = hotelService.setHotelAgent(hotelId, agentId);
       // sendMqMessage(hotelId);
        return res;
    }

    @NeedToken
    @ApiOperation(value = "酒店快速抢单", notes = "抢单成功返回true,失败返回错误信息")
    @PostMapping(value = "/rob/order")
    public AjaxResponseBody<Boolean> robOrder(@Validated OrderPickWebSocket orderPickWebSocket,
                                              @RequestParam(name = "strRoomIds") String strRoomIds) {
        AccountInfo loginUser = AccountUtils.getLoginUser();
        if (!loginUser.getType().equals(AccountType.HotelManager)) {
            throw new ServiceException("当前操作人非法");
        }
        if (null == strRoomIds) {
            throw new ServiceException("房间id不能为空");
        }
        List<Integer> roomIds = Splitters.splitToInteger(strRoomIds, Splitters.COMMA);
        orderPickWebSocket.setRoomIds(roomIds);
        orderPickRecordService.robOrder(orderPickWebSocket);
        return AjaxResponseBody.success(true);
    }

    @NeedToken
    @ApiOperation(value = "酒店设置是否手动抢单", notes = "抢单成功返回true,失败返回错误信息")
    @ApiImplicitParam(paramType = "query", name = "isRob", value = "0自动抢单，1手动抢单", dataType = "Integer")
    @PostMapping(value = "/is/rob")
    public AjaxResponseBody<Boolean> isRob(@RequestParam(name = "isRob") Integer isRob) {
        if (null == isRob) {
            throw new ServiceException("参数必传");
        }
        if (0 != isRob && 1 != isRob) {
            throw new ServiceException("参数值有误");
        }
        AccountInfo loginUser = AccountUtils.getLoginUser();
        if (!loginUser.getType().equals(AccountType.HotelManager)) {
            throw new ServiceException("当前操作人非法");
        }
        hotelService.isRob(loginUser, isRob);
        return AjaxResponseBody.success(true);
    }

    @NeedToken
    @ApiOperation(value = "查看酒店抢单状态", notes = "返回0(自动抢单)和1(手动抢单)")
    @PostMapping(value = "/rob/status")
    public AjaxResponseBody<Integer> robStatus() {
        AccountInfo loginUser = AccountUtils.getLoginUser();
        if (!loginUser.getType().equals(AccountType.HotelManager)) {
            throw new ServiceException("当前操作人非法");
        }
        return AjaxResponseBody.success(hotelService.robStatus(loginUser));
    }

    /**
     * 发送酒店修改信息到mq
     * @param hotelId
     */
    private void sendMqMessage(Integer hotelId)
    {
        List<String> sourceIds = new ArrayList<>();
        sourceIds.add(String.valueOf(hotelId));
        mQProducerService.sendEsUpdate(new EsUpdateMessage().setType("hotel").setSourceType("yyks").setSourceIds(sourceIds), 0);
    }


}